package it.unica.informatica.enotes.adapter;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.method.DigitsKeyListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

import it.unica.informatica.enotes.NotesActivity;
import it.unica.informatica.enotes.R;

/**
 * This class manages a single row of the ListView that show the list of all the tags for a note
 *
 * @author Mirko Marras
 * @version 1.0
 */
public class TagItemAdapter extends BaseAdapter {

   private Context notesActivity;
   private Button tabButton;
   private boolean editState;
   private List<String> tags;
   private LayoutInflater inflater;

   /**
    * Construct a new adapter to manage the list of all the tags associated to the current note
    *
    * @param notesActivity The activity that manages the data of the current note
    * @param tabButton     The tab button associated to the tags list
    * @param editState     The EditState for the current note: ONLY VIEW or EDIT
    * @param tags          The list of all the tags associated to the current note
    */
   public TagItemAdapter(NotesActivity notesActivity, Button tabButton, boolean editState, List<String> tags) {
      this.notesActivity = notesActivity;
      this.tabButton = tabButton;
      this.editState = editState;
      this.tags = tags;
      this.inflater = (LayoutInflater) notesActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   }

   /**
    * Get the number of the tags associated to the current note
    *
    * @return The number of the tags associated to the current note
    */
   @Override
   public int getCount() {
      return tags.size();
   }

   /**
    * Get the tag associated to the position in the list
    *
    * @param position The position of the tag to retrieve
    * @return The row of the list associated to the position
    */
   @Override
   public Object getItem(int position) {
      return tags.get(position);
   }

   /**
    * Remove the tag at the position
    *
    * @param from The position of the tag to remove
    */
   public void remove(int from) {
      tags.remove(from);
   }

   /**
    * Insert a new tag at the position
    *
    * @param item The tag to insert
    * @param to   The position where insert the tag
    */
   public void insert(String item, int to) {
      tags.add(to, item);
   }

   /**
    * Get the ID of the tag associated to the position in the list
    *
    * @param position The position of the tag ID to retrieve
    * @return The tag ID of the tag associated to the position
    */
   @Override
   public long getItemId(int position) {
      return position;
   }

   /**
    * This class contains the view objects associated with the views of the layout
    *
    * @author Mirko Marras
    * @version 1.0
    */
   private class RowLayout {
      TextView tagName;

      ImageView deleteButton;
      ImageView editButton;
   }

   /**
    * Construct a view that represents a row in the list of all the tags for the current note
    *
    * @param position    The position in the list for the current tag
    * @param convertView The view to which the current tag belongs
    * @param parent      The parent to which the current tag belongs
    * @return The view that represents a row in the list of all the tags
    */
   @Override
   public View getView(final int position, View convertView, ViewGroup parent) {
      /* Retrieve the current tag to show */
      final String selectedTag = tags.get(position);

      /* Initialize the components of the row layout */
      RowLayout holder = new RowLayout();
      View rowView = inflater.inflate(R.layout.tag_item, null);

      /* Bind the view objects with the views of the layout */
      holder.tagName = (TextView) rowView.findViewById(R.id.tag_item);
      holder.editButton = (ImageView) rowView.findViewById(R.id.action_edit_attachment);
      holder.deleteButton = (ImageView) rowView.findViewById(R.id.action_delete_tag);

      /* Set the name of the current tag */
      holder.tagName.setText(selectedTag);

      /* Set the logic of the edit button used to modify the name of the tag */
      holder.editButton.setId(position);
      holder.editButton.setVisibility((editState) ? View.VISIBLE : View.GONE);

      holder.editButton.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
            final View selectView = v;

            /* Create and show a dialog to allow the user to modify the name of the selected tag */
            final AlertDialog.Builder alert = new AlertDialog.Builder(notesActivity);
            alert.setTitle(R.string.action_rename);

            final EditText input = new EditText(notesActivity);
            input.setText(selectedTag);
            input.setSelectAllOnFocus(true);

            InputFilter alphaNumericFilter = new InputFilter() {
               @Override
               public CharSequence filter(CharSequence arg0, int arg1, int arg2, Spanned arg3, int arg4, int arg5)
               {
                  for (int k = arg1; k < arg2; k++) {
                     if (!Character.isLetterOrDigit(arg0.charAt(k))) {
                        return "";
                     }
                  }
                  return null;
               }
            };
            input.setFilters(new InputFilter[]{ alphaNumericFilter});

            alert.setView(input);

            alert.setPositiveButton(R.string.ok_button, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int whichButton) {
                  /* Retrieve and show the new tag */
                  String newTag = input.getText().toString();

                  /* Check if the new tag contains at least one character */
                  if (!newTag.isEmpty()) {
                     if (!tags.contains(newTag)) { /* Check if the new name is already used */
                        tags.set(selectView.getId(), newTag);
                        notifyDataSetChanged();
                     } else { /* If the tag is already used */
                        Toast.makeText(notesActivity.getApplicationContext(), R.string.toast_tag_duplicate, Toast.LENGTH_SHORT).show();
                     }
                  } else { /* If the new tag is empty */
                     Toast.makeText(notesActivity.getApplicationContext(), R.string.toast_tag_error, Toast.LENGTH_SHORT).show();
                  }
               }
            });

            alert.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int whichButton) {

               }
            });

            alert.show();

            /* Automatically show the software keyboard */
            InputMethodManager imm = (InputMethodManager) notesActivity.getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
         }
      });

      /* Set the logic of the delete button used to delete the tag */
      holder.deleteButton.setId(position);
      holder.deleteButton.setVisibility((editState) ? View.VISIBLE : View.GONE);

      holder.deleteButton.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
         /* Retrieve and remove the selected tag */
         tags.remove(v.getId());
         tabButton.setText(tabButton.getTag() + " (" + tags.size() + ")");

         notifyDataSetChanged();
         }
      });

      return rowView;
   }

}